/*
 * tcpserver.h
 *
 *  Created on: 2011-8-24
 *      Author: chenl
 *     Purpose:
 *        Note:
 */

#ifndef TCPSERVER_H_
#define TCPSERVER_H_

#ifndef WIN32
#include <sys/type.h>
#include <sys/socket.h>
#endif

#include "common_connect.h"

class CTcpServer
{
public:
	CTcpServer() : m_bStarted(false), m_nListenFD(enmInvalidFD)
	{
		bzero(&m_serverAddr, sizeof(m_serverAddr));
	}
	virtual ~CTcpServer()
	{
		assert(GetConnectonStatus() == CConnect::enmConnStatus_Closed);
	}
public:
	int32_t Start()
	{
		if (m_bStarted)
		{
			return S_FALSE;
		}
		m_nListenFD = socket(AF_INET, SOCK_STREAM, 0);
		if (m_nListenFD <= 0)
		{
			return E_CREATESOCKERR;
		}
		m_serverAddr.sin_family = AF_INET;
		m_serverAddr.sin_addr = htons(INADDR_ANY);
		m_serverAddr.sin_port = htons(GET_CONFIG_INSTANCE().GetPort());

		int32_t ret = S_OK;
		int on = 1;
		ret = setsockopt(m_nListenFD, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
		if (0 > ret)
		{
			return ret;
		}
		ret = bind(m_nListenFD, (struct sockaddr_in *)&m_serverAddr, sizeof(m_serverAddr));
		if (0 > ret)
		{
			return ret;
		}
		ret = listen(m_nListenFD, SOMAXCONN);
		if (0 > ret)
		{
			return ret;
		}
		m_bStarted = true;
		return ret;
	}
	int32_t Stop()
	{
		close(m_nListenFD);
		m_bStarted = false;
		return S_OK;
	}
	int32_t Accept(int &fd)
	{
		fd = accept(m_nListenFD, NULL, NULL);
		if (-1 == fd)
		{
			return E_SOCKACCEPTERR;
		}
		return S_OK;
	}
	int GetFD() const
	{
		return m_nListenFD;
	}
private:
	CTcpServer(const CTcpServer&);
	CTcpServer &operator==(const CTcpServer&);
private:
	bool m_bStarted;
	int m_nListenFD;
	struct sockaddr_in m_serverAddr;
};

#endif /* TCPSERVER_H_ */
